define('framework/datatree/DataTreeDirective', ["angular"], function (angular) {
        var DataTreeProto = DataTree.prototype;

        function DataTree($scope, $element, $attrs, $treeHelper) {
            this.scope = $scope;
            this.$element = $element;
            this.$attrs = $attrs;
            this.treeHelper = $treeHelper;
        }

        //根据id获取结点
        DataTreeProto.searchNodeById = function (idProp) {
            var me = this,
                ele;
            ele = me.treeHelper.searchNodeByTd(me.scope.treeData, idProp);
            if (ele) {
                return ele.originData;
            }
        };

        //查询子结点
        DataTreeProto.searchChildren = function (idProp) {
            var me = this,
                children = [],
                ele, i, len;
            ele = me.treeHelper.searchNodeByTd(me.scope.treeData, idProp);
            if (ele && ele.children && ele.children.length > 0) {
                for (i = 0, len = ele.children.length; i < len; i++) {
                    children.push(ele.children[i].originData);
                }
            }
            return children;
        };

        //根据显示值获取结点
        DataTreeProto.searchNodeByValue = function (value) {
            var me = this,
                result = [],
                nodes, i, len;
            nodes = me.treeHelper.findNodeByValue(this.scope.treeData, value);
            if (nodes && nodes.length > 0) {
                for (i = 0, len = nodes.length; i < len; i++) {
                    result.push(nodes[i].originData);
                }
            }
            return result;
        };

        //设置隐藏或显示
        DataTreeProto.displayNode = function (idProp, show) {
            var me = this,
                el, i, len;
            if (angular.isUndefined(show)) {
                show = true;
            }
            if (angular.isArray(idProp) && idProp.length > 0) {
                for (i = 0, len = idProp.length; i < len; i++) {
                    el = me.treeHelper.searchNodeByTd(this.scope.treeData, idProp[i]);
                    el.display = show;
                }
            } else {
                el = me.treeHelper.searchNodeByTd(this.scope.treeData, idProp);
                el.display = show;
            }
        };

        //设置编辑状态
        DataTreeProto.editable = function (idProp, editable) {
            var me = this,
                el, i, len;
            if (angular.isUndefined(editable)) {
                editable = true;
            }
            if (angular.isArray(idProp) && idProp.length > 0) {
                for (i = 0, len = idProp.length; i < len; i++) {
                    el = me.treeHelper.searchNodeByTd(this.scope.treeData, idProp[i]);
                    el.editable = editable;
                }
            } else {
                el = me.treeHelper.searchNodeByTd(this.scope.treeData, idProp);
                el.editable = editable;
            }
        };

        //展开结点
        DataTreeProto.expandNode = function (idProp, expand, isChildren) {
            var me = this,
                scope = this.scope,
                config = scope.config,
                paramArg, item;
            expand = expand !== false;
            item = me.treeHelper.searchNodeByTd(scope.treeData, idProp);
            if (angular.isUndefined(scope.disabled) && item.disabled === false) {
                paramArg = {
                    record: item.originData
                };
                if (item.expanded === false && expand === true) {
                    if (!(scope.beforeExpand(paramArg) === false)) {
                        if (scope.async) {
                            scope.source.params[config.idProp] = item.idProp;
                            if (isChildren === true) {
                                scope.source.params.child = "true";
                            }
                            scope.source.doRequestData(scope.source.params, function (_dataSource) {
                                var records, children;
                                records = angular.copy(_dataSource.records);
                                if (item) {
                                    if (!records || records.length === 0) {
                                        item.type = "leaf";
                                    } else {
                                        children = me.treeHelper.createChildren(item, records, config, isChildren);
                                        angular.extend(item.children, children);
                                        for (var i = 0; i < children.length; i++) {
                                            children[i].parent = item;
                                        }
                                    }
                                }
                                item.expanded = !item.expanded;
                                scope.onExpand(paramArg);
                            }, true);
                        } else {
                            item.expanded = !item.expanded;
                            scope.onExpand(paramArg);
                        }
                    }
                } else if (item.expanded === true && expand === false) {
                    item.expanded = !item.expanded;
                }
            }
        };

        //根据value设置当前行
        DataTreeProto.gotoRow = function (value, index) {
            var me = this,
                result = -1,
                onSelect = me.scope.onSelect,
                ele, items, selectParams;
            if (index === undefined) index = 0;
            items = me.treeHelper.findNodeByDisplay(me.scope.treeData, value);
            if (items && items.length > 0) {
                ele = items[index];
                if (ele) {
                    selectParams = {
                        record: ele.originData
                    };
                    if (me.canSetCurrentRow(ele)) {
                        me.scope.currentRow = ele.originData;
                        ele.selected = true;
                        me.scope._currentRow.selected = false;
                        me.scope._currentRow = ele;
                        me.scope._currentRow.selected = true;
                        ele.expanded = true;
                        me.expandAllParent(ele);
                        if (onSelect !== undefined) {
                            onSelect(selectParams);
                        }
                    }
                    result = index === items.length - 1 ? 0 : index + 1;
                }
            }
            return result;
        };
        //根据id设置当前行
        DataTreeProto.setCurrentRow = function (idProp) {
            var me = this,
                ele;
            ele = me.treeHelper.searchNodeByTd(this.scope.treeData, idProp);
            if (!ele) return;
            ele.selected = true;
            this.scope.currentRow = ele.originData;
            this.scope._currentRow.selected = false;
            this.scope._currentRow = ele;
            ele.expanded = true;
            me.expandAllParent(ele);
        };
        //设置只读属性
        DataTreeProto.readonly = function (idProp, readonly) {
            var me = this,
                el, i, len;
            if (angular.isUndefined(readonly)) {
                readonly = true;
            }
            if (angular.isArray(idProp) && idProp.length > 0) {
                for (i = 0, len = idProp.length; i < len; i++) {
                    el = me.constructor.searchNodeByTd(this.scope.treeData, idProp[i]);
                    el.readonly = readonly;
                }
            } else {
                el = me.treeHelper.searchNodeByTd(this.scope.treeData, idProp);
                el.readonly = readonly;
            }
        };
        //设置disable属性
        DataTreeProto.disabled = function (idProp, disabled) {
            var me = this,
                el, i, len;
            if (angular.isUndefined(disabled)) {
                disabled = true;
            }
            if (angular.isArray(idProp) && idProp.length > 0) {
                for (i = 0, len = idProp.length; i < len; i++) {
                    el = me.treeHelper.searchNodeByTd(this.scope.treeData, idProp[i]);
                    el.disabled = disabled;
                }
            } else {
                el = me.treeHelper.searchNodeByTd(this.scope.treeData, idProp);
                el.disabled = disabled;
            }
        };
        //设置结点的勾选状态
        DataTreeProto.check = function (idProp, checked) {
            var me = this,
                el, i, len;
            if (angular.isUndefined(checked)) {
                checked = true;
            }
            if (angular.isArray(idProp) && idProp.length > 0) {
                for (i = 0, len = idProp.length; i < len; i++) {
                    el = me.treeHelper.searchNodeByTd(me.scope.treeData, idProp[i]);
                    if (!el) continue;
                    if (checked) {
                        me.doCheck(el);
                    } else {
                        if (el.checked === true) {
                            me.updateCheckChanges(el);
                            el.checked = false;
                        } else {
                            el.checked = false;
                        }
                        me.treeHelper.removeItem(me.scope._chooseItems, el);
                    }
                }
            } else {
                el = me.treeHelper.searchNodeByTd(me.scope.treeData, idProp);
                if (!el) return;
                if (checked) {
                    me.doCheck(el);
                } else {
                    if (el.checked === true) {
                        me.updateCheckChanges(el);
                        el.checked = false;
                    } else {
                        el.checked = false;
                    }
                    me.treeHelper.removeItem(me.scope._chooseItems, el);
                }
            }
        };

        //执行勾选
        DataTreeProto.doCheck = function (item) {
            var me = this;
            if (me.canCheck(item)) {
                item.checked = true;
                me.updateCheckChanges(item);
                if (!me.treeHelper.contains(me.scope._chooseItems, item, me.scope.config)) {
                    me.scope._chooseItems.push(item);
                }

            }
        };

        //展开所有父结点
        DataTreeProto.expandAllParent = function (item) {
            var parent = item.parent,
                flag = parent !== null;
            while (flag) {
                parent.expanded = true;
                parent = parent.parent;
                flag = parent !== null;
            }
        };
        //重截数据源
        DataTreeProto.reload = function (records) {
            var me = this,
                paramArg;
            if (angular.isArray(records) && records.length > 0) {
                me.scope.treeData = [];
                me.scope.currentRow = {};
                me.scope._currentRow.selected = false;
                me.scope._currentRow = {};
                me.scope._chooseItems = [];
                me.scope.treeData = me.treeHelper.buildTree(records, me.scope.config);
                me.treeHelper.pushCheckedItem(me.scope.treeData, me.scope);
                paramArg = {
                    record: records
                };
                me.scope.onLoadSuccess(paramArg);
            } else {
                if (me.scope.async) {
                    if (me.scope.source.params === undefined) {
                        me.scope.source.params = {};
                    }
                    me.scope.dataSource.doRequestData(me.scope.source.params, function (dataSource) {
                        records = angular.copy(dataSource.records);
                        me.scope.treeData = [];
                        me.scope.currentRow = {};
                        me.scope._currentRow.selected = false;
                        me.scope._currentRow = {};
                        me.scope._chooseItems = [];
                        me.scope.treeData = me.treeHelper.buildTree(records, me.scope.config);
                        me.treeHelper.pushCheckedItem(me.scope.treeData, me.scope);
                        paramArg = {
                            record: records
                        };
                        me.scope.onLoadSuccess(paramArg);
                    }, true);
                }
            }
        };

        //选中结点的所有子孙
        DataTreeProto.selectChild = function (item, dataTree) {
            var me = dataTree || this,
                i, len, el, children;
            children = item.children || [];
            for (i = 0, len = children.length; i < len; i++) {
                el = children[i];
                //可以选择，并且还没有被选中
                if (me.canCheck(el) && !el.checked) {
                    if (!el.checked) {
                        el.checked = true;
                        me.updateCheckChanges(el);
                    }
                    if (me.treeHelper.contains(me.scope._chooseItems, el) === false) {
                        me.scope._chooseItems.push(el);
                    }
                }
                if (el.children && el.children.length > 0) {
                    arguments.callee(el, me);
                }
            }
        };

        //选中结点的所有父结点
        DataTreeProto.selectParent = function (item, dataTree) {
            var me = dataTree || this,
                parentProp, parentNode;
            if (me.scope.cascadeMode && me.scope.cascadeMode === "limit") {
                parentProp = item.parentProp;
                if (parentProp && parentProp !== "") {
                    parentNode = me.treeHelper.searchNodeByTd(me.scope.treeData, parentProp);
                    if (parentNode) {
                        //可以选择，并且还没有被选中
                        if (me.canCheck(parentNode) && !parentNode.checked) {
                            if (!parentNode.checked) {
                                parentNode.checked = true;
                                me.updateCheckChanges(parentNode);
                            }
                            if (!me.treeHelper.contains(me.scope._chooseItems, parentNode)) {
                                me.scope._chooseItems.push(parentNode);
                            }
                        }
                        arguments.callee(parentNode, me);
                    }
                }
            }
        };

        //从选中数据中删除结点的所有子孙
        DataTreeProto.unSelectChildren = function (item, dataTree) {
            var me = dataTree || this,
                i, len, el, children;
            children = item.children || [];
            for (i = 0, len = children.length; i < len; i++) {
                el = children[i];
                //删除已经被选中的结点
                if (me.canCancelCheck(el)) {
                    if (el.checked) {
                        el.checked = false;
                        me.updateCheckChanges(el);
                    }
                    me.treeHelper.remove(me.scope._chooseItems, el);
                }
                if (el.children && el.children.length > 0) {
                    arguments.callee(el, me);
                }
            }
        };

        //判断结点是否可选
        DataTreeProto.canCheck = function (item) {
            var me = this,
                flag = false,
                result = false;
            if (item.showBox && !me.scope.disabled) {
                if (!item.readonly && !item.disabled) {
                    flag = true;
                }
            }
            if (flag) {
                if (me.scope.radio) {
                    if (item.type === 'leaf') {
                        result = true;
                    }
                } else {
                    if (item.type === 'leaf') {
                        result = true;
                    } else if (me.scope.allowChooseParent) {
                        result = true;
                    }
                }
            }
            return result;
        };

        //判断结点是否可取消勾选
        DataTreeProto.canCancelCheck = function (item) {
            var me = this;
            if (item.showBox && item.checked) {
                if (!me.scope.disabled) {
                    if (!item.readonly && !item.disabled) {
                        return true;
                    }
                }
            }
            return false;
        };

        //凑数是否可设为当前行
        DataTreeProto.canSetCurrentRow = function (item, $event) {
            var me = this,
                beforeSelect = me.scope.onBeforeSelect,
                result = false,
                selectParams;
            selectParams = {
                $event: $event,
                record: item.originData
            };
            if (!me.scope.disabled) {
                if (beforeSelect === undefined || beforeSelect(selectParams) !== false) {
                    result = true;
                }
            }
            return result;
        };

        //取消其他结点的编辑状态
        DataTreeProto.cancelOtherEditable = function (item) {
            var me = this,
                treeData = me.scope.treeData;
            me.treeHelper._cancelOtherEditable(treeData, item);
        };

        //清除所有勾选值
        DataTreeProto.clearChooseItems = function () {
            var me = this,
                i, len, el;
            len = me.scope._chooseItems.length;
            for (i = 0; i < len; i++) {
                el = me.scope._chooseItems[i];
                el.checked = false;
            }
            me.scope._chooseItems = [];
        };

        //保存checked修改值
        DataTreeProto.updateCheckChanges = function (item) {
            var me = this,
                flag = false,
                i, len, ele, el;
            for (i = 0, len = me.scope.checkChanges.length; i < len; i++) {
                ele = me.scope.checkChanges[i];
                for (var idProp in ele) {
                    if (ele.hasOwnProperty(idProp)) {
                        if (idProp === item.idProp) {
                            flag = true;
                            if (ele[idProp] !== item.checked) {
                                me.scope.checkChanges.splice(i, 1);
                            }
                            break;
                        }
                    }
                }
            }
            if (!flag) {
                el = {};
                el[item.idProp] = item.checked;
                me.scope.checkChanges.push(el)
            }
        };
        //获取树中所有check改变值
        DataTreeProto.getCheckChanges = function () {
            var me = this;
            return me.scope.checkChanges;
        };
        //清除所有check改变状态
        DataTreeProto.clearCheckChanges = function () {
            var me = this;
            me.scope.checkChanges = [];
        };

        return function ($compile, $dataSourceManager, $templateCache, $dataTreeManager, $treeHelper) {
            var recursiveTemplate, template;
            template = '<div class="tree">\n <div ng-disabled="disabled" class="tree-head"> \n <ul class="tree-head-selecteds"> \n <li>{{titleExpress===""?"":(titleExpress || "选择：")}}</li> \n <li ng-disabled="disabled" ng-repeat="item in _chooseItems" ng-click="deleteChooseItem(item)">{{item.displayExpress}}</li> \n </ul> \n <button ng-if="showRechoose"  ng-disabled="disabled" class="btn tree-btn-reset"  ng-click="clearChooseItems()">重选</button> \n </div> \n <div class="tree-body"> \n <ul tree-nodes ng-model="treeData"> \n <li tree-node  ng-repeat="item in treeData"  ng-include="\'/datatree/template\'"></li> \n </ul> \n </div> \n </div>';
            recursiveTemplate = '<div class="tree-item" ng-click="rowClick($event,item)"> \n <i class="fi tree-fi-folder"  ng-click="expandNode($event,item)"></i> \n <i class="fi tree-fi-clickbox" ng-click="chooseItem($event,item)"></i> \n <span ng-dblclick="onDblClick($event,item)" ng-if="item.editable===false"  outer-scope="item.itemRootScope" render-item-class="item.itemClass" render-item-class-locals="{record:item.originData}" >{{item.displayExpress}}</span> \n <input style="width:50%;" ng-blur="onBlur($event,item)"  ng-keypress="onKeyPress($event,item)" ng-if="item.editable===true && item.readonly===false && item.disabled===false"   outer-scope="item.itemRootScope" render-item-class="item.itemClass" render-item-class-locals="{record:item.originData}" value="{{item.displayExpress}}"/> \n </div> \n <ul tree-nodes  ng-model="item.children"> \n <li tree-node  ng-repeat="item in item.children"   ng-include="\'/datatree/template\'"></li> \n </ul>';
            $templateCache.put("/datatree/template", recursiveTemplate);
            return {
                restrict: 'E',
                replace: true,
                scope: {
                    currentRow: '=',
                    sourceName: '@',
                    showSelect: '&',
                    disabled: '@',
                    chooseItems: '=',
                    onBeforeSelect: '&',
                    onSelect: '&',
                    onBeforeCheck: '&',
                    onCheck: '&',
                    titleExpress: '@',
                    onLoadSuccess: '&',
                    treeName: '@',
                    displayItem: '&',
                    editable: '&',
                    beforeRename: '&',
                    onRename: '&',
                    readonlyItem: '&',
                    disabledItem: '&',
                    beforeExpand: '&',
                    onExpand: '&'
                },
                template: template,
                require: ['gDataTree', '?^ngModel'],
                link: function (scope, element, attrs, ctrls) {
                    var displayExpress = attrs.displayExpress,
                        valueProp = attrs.valueProp,
                        parentProp = attrs.parentProp,
                        idProp = attrs.idProp,
                        hasChildProp = attrs.hasChildProp,
                        checkedProp = attrs.checkedProp,
                        mode = attrs.mode || 'radio',
                        isExpandAll = attrs.isExpandAll || 'false',
                        async = attrs.async || 'false',
                        allowCascadeSelect = attrs.allowCascadeSelect || 'false',
                        allowChooseParent = attrs.allowChooseParent || 'true',
                        width = attrs.width,
                        height = attrs.height,
                        showRechoose = attrs.showRechoose || 'true',
                        showCheckBox = attrs.showCheckBox || 'true',
                        cascadeMode = attrs.cascadeMode || 'default',
                        doubleEdit = attrs.doubleEdit || 'false',
                        config, dataTree, unitRegExp, ngModel;
                    scope.checkChanges = [];
                    scope.async = async === 'true';
                    //保存当前行数据
                    scope.currentRow = {};
                    scope._currentRow = {};
                    scope.cascadeMode = cascadeMode;
                    scope.showCheckBox = showCheckBox === 'true';
                    scope.doubleEdit = doubleEdit === 'true';
                    scope.allowCascadeSelect = allowCascadeSelect === 'true';
                    dataTree = ctrls[0];
                    ngModel = ctrls[1];
                    //表示数据源中树关系字段
                    config = {};
                    config.idProp = idProp;
                    config.parentProp = parentProp;
                    config.hasChildProp = hasChildProp;
                    config.valueProp = valueProp;
                    config.displayExpress = displayExpress;
                    config.async = async;
                    config.mode = mode;
                    config.allowChooseParent = allowChooseParent;
                    config.checkedProp = checkedProp;
                    config.showBox = scope.showSelect;
                    config.isExpandAll = isExpandAll;
                    config.displayItem = scope.displayItem;
                    config.editable = scope.editable;
                    config.readonlyItem = scope.readonlyItem;
                    config.disabledItem = scope.disabledItem;

                    scope.config = config;
                    scope.radio = (mode === 'radio');
                    scope.showRechoose = (showRechoose === 'true');
                    scope.allowChooseParent = (allowChooseParent === 'true');
                    //已选中的记录
                    scope._chooseItems = [];
                    //已经转化好的树型数据
                    scope.treeData = [];
                    if (scope.treeName) {
                        $dataTreeManager.registerDataTree(scope.treeName, dataTree);
                    }
                    //设置控件的宽度
                    unitRegExp = /^[0-9]+(%|in|cm|mm|pt|pc|ex|em|px)?$/g;
                    if (width) {
                        if (unitRegExp.test(width)) {
                            element.css("width", width);
                        } else {
                            throw "宽度设置错误";
                        }
                    }
                    //设置控件的高度
                    unitRegExp = /^[0-9]+(%|in|cm|mm|pt|pc|ex|em|px)?$/g;
                    if (height) {
                        if (unitRegExp.test(height)) {
                            element.css("height", height);
                        } else {
                            throw "高度设置错误";
                        }
                    }

                    //树的初始化
                    function initTreeData(dataSource) {
                        var records, paramArg;
                        records = angular.copy(dataSource.records);
                        if (!scope.source) {
                            scope.source = dataSource;
                        }
                        scope.treeData = $treeHelper.buildTree(records, scope.config);
                        $treeHelper.pushCheckedItem(scope.treeData, scope);
                        paramArg = {
                            record: records
                        };
                        scope.onLoadSuccess(paramArg);
                    }


                    //加载数据
                    if (async === "false") {
                        scope.$on(scope.sourceName, function (event, dataSource) {
                            initTreeData(dataSource);
                        });
                    } else {
                        $dataSourceManager.getDataSource(scope.sourceName).then(function (dataSource) {
                            if (dataSource.params === undefined) {
                                dataSource.params = {};
                            }
                            dataSource.doRequestData(dataSource.params, initTreeData, true);
                        });
                    }

                    //点击重选执行的函数
                    scope.clearChooseItems = function () {
                        if (angular.isUndefined(scope.disabled)) {
                            dataTree.clearChooseItems();
                        }
                    };

                    //点击上面选中值文字执行的函数
                    scope.deleteChooseItem = function (item) {
                        if (!scope.disabled) {
                            $treeHelper.remove(scope._chooseItems, item);
                            item.checked = false;
                            dataTree.updateCheckChanges(item);
                            //级联删除
                            if (scope.allowCascadeSelect && !scope.radio) {
                                dataTree.unSelectChildren(item);
                            }
                        }
                    };

                    if (ngModel) {
                        ngModel.$render = function () {
                            var modelValues, itemValues, items, i, len, el, _i, _len;
                            dataTree.clearChooseItems();
                            modelValues = ngModel.$viewValue;
                            if (!modelValues) return;
                            if (scope.radio) {
                                items = $treeHelper.findNodeByValue(scope.treeData, modelValues);
                                if (items && items.length > 0) {
                                    if (items[0].showBox && items[0].type === "leaf") {
                                        items[0].checked = true;
                                        scope._chooseItems.push(items[0]);
                                    }
                                }
                            } else {
                                if (modelValues && modelValues.length > 0) {
                                    itemValues = modelValues.split(",");
                                }
                                for (i = 0, len = itemValues.length; i < len; i++) {
                                    items = $treeHelper.findNodeByValue(scope.treeData, itemValues[i]);
                                    if (items && items.length > 0) {
                                        for (_i = 0, _len = items.length; _i < _len; _i++) {
                                            el = items[_i];
                                            if ((el.showBox && scope.allowChooseParent && el.type === "branch") || (el.type === "leaf" && el.showBox)) {
                                                el.checked = true;
                                                scope._chooseItems.push(el);
                                            }
                                        }
                                    }
                                }
                            }
                        };
                        //当树中已选中项发生改就时，更改ngModel的值。
                        scope.$watchCollection("_chooseItems", function (newValue) {
                            var chooseItems = [], modelValue = "";
                            angular.forEach(newValue, function (item) {
                                modelValue += item.valueProp + ",";
                                chooseItems.push(item.originData);
                            });
                            scope.chooseItems = chooseItems;
                            chooseItems = null;
                            if (modelValue && modelValue.length > 0) {
                                modelValue = modelValue.substring(0, modelValue.length - 1);
                            }
                            if (ngModel.$viewValue !== modelValue) {
                                if (scope.$root.$$phase) {
                                    ngModel.$setViewValue(modelValue);
                                } else {
                                    scope.$apply(function () {
                                        ngModel.$setViewValue(modelValue);
                                    });
                                }
                            }
                        });
                    }

                },
                controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
                    $scope.dataTree = new DataTree($scope, $element, $attrs, $treeHelper);
                    return $scope.dataTree;
                }]
            }
        }
    }
);
